package com.linkelee.api.token;



import lombok.Builder;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;


import javax.servlet.http.HttpServletRequest;
import java.util.concurrent.TimeUnit;

/**
 * token工具类
 *
 * @author lsl
 * @since 2019-03-25
 */

@Builder
@Data
@Slf4j
public class TokenHelper {

    public static final String AFBI_TOKEN_PREFIX = "afbi-token:";

    public static final String AFBI_TOKEN_ENABLE_PREFIX = "enable-token:";

    public static final String REQUEST_HEADER_PARAM_TOKEN = "token";

    public static final long AFBI_ENABLE_EXPIRE_TIME = 10;


    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 设置token内容
     *
     * @param token token
     * @param value 内容object
     */
    public void setToken(String token, Object value) {
        log.info("token object save---" + value.toString());
        redisTemplate.opsForValue().set(buildToken(token), value);
    }

    /**
     * 设置token内容并设置过期时间
     *
     * @param value
     * @return
     * @throws Exception
     */
    public String setTokenExpire(Object value) throws Exception {
        String token = TokenGenerator.generateValue();
        setTokenExpire(token, value);
        return token;
    }

    /**
     * 设置token内容和过期时间并返回token
     *
     * @param value
     */
    public void setTokenExpire(String token, Object value) throws Exception {
        log.info("token object saveExpire---" + value.toString());
        redisTemplate.opsForValue().set(buildToken(token), value, AFBI_ENABLE_EXPIRE_TIME, TimeUnit.MINUTES);
    }

    /**
     * 生效token
     *
     * @param token
     * @param key
     */
    public void enableToken(String token, String key) {
        log.info("token enable save--- key:" + key + " token:" + token);
        // 设置enable键
        redisTemplate.opsForValue().set(buildKey(key), token);
    }

    /**
     * 重设过期时间
     *
     * @param token
     */
    public void expireToken(String token) {
        redisTemplate.expire(buildToken(token), AFBI_ENABLE_EXPIRE_TIME, TimeUnit.MINUTES);
    }


    /**
     * 获取token中的内容
     *
     * @param token
     * @return
     */
    public Object getToken(String token) {
        Object value = redisTemplate.opsForValue().get(buildToken(token));
        log.info("token object get---" + value.toString());
        return value;
    }

    /**
     * 从请求中获取token中的内容
     *
     * @param request
     * @return
     */
    public Object getToken(HttpServletRequest request) {
        String token = request.getHeader(REQUEST_HEADER_PARAM_TOKEN);
        if (Strings.isEmpty(token)) {
            return null;
        }
        return getToken(token);
    }


    /**
     * 检查是否token已经存在
     *
     * @param token
     * @return
     */
    public boolean checkToken(String token) {
        return redisTemplate.hasKey(buildToken(token));
    }

    /**
     * 检查token是否生效
     *
     * @param key
     * @param checkToken
     * @return
     */
    public boolean checkEnable(String key, String checkToken) {
        String token = String.valueOf(redisTemplate.opsForValue().get(buildKey(key)));
        boolean flag = checkToken.equals(token);
        // 如果token已经失效了,则直接删除token,节省redis内存资源
        if (!flag) {
            delToken(checkToken);
        }
        return flag;
    }

    /**
     * redis生成token
     * token = afbi的token前缀+生成的token
     *
     * @param token
     * @return
     */
    public String buildToken(String token) {
        String tokenAfbi = AFBI_TOKEN_PREFIX + token;
        log.info("token ---" + token);
        return tokenAfbi;
    }

    /**
     * redis生成enable
     * key = afbi的enable前缀+业务的key
     *
     * @param key
     * @return
     */
    public String buildKey(String key) {
        String enableAfbi = AFBI_TOKEN_ENABLE_PREFIX + key;
        log.info("key ---" + key);
        return enableAfbi;
    }

    /**
     * 查看token是否生效
     *
     * @param token
     * @return
     */
    public boolean checkTokenEnable(String token) {
        Object user =  getToken(token);
        if (user == null) {
            return false;
        }
        String key = "";
        if (Strings.isEmpty(key)) {
            return false;
        }
        return checkEnable(key, token);
    }

    /**
     * 注销的时候默认删除token
     *
     * @param token
     */
    public void delToken(String token) {
        redisTemplate.delete(buildToken(token));
    }
}
